package com.liveMobile.Screen.recorder;

import static android.content.ContentValues.TAG;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ServiceInfo;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;

import androidx.core.app.NotificationCompat;
import androidx.core.util.Consumer;

import  com.liveMobile.Screen.utils.*;
import com.pedro.common.ConnectChecker;
//import com.pedro.encoder.input.sources.audio.AudioSource;
//import com.pedro.encoder.input.sources.audio.InternalAudioSource;
//import com.pedro.encoder.input.sources.audio.MixAudioSource;
import com.pedro.library.util.sources.audio.MicrophoneSource;
import com.pedro.library.util.sources.video.NoVideoSource;
import com.pedro.library.base.recording.RecordController;
import com.pedro.library.generic.GenericStream;
import com.pedro.library.util.sources.video.ScreenSource;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;


public class ScreenRecorder extends Service implements ConnectChecker {
    public  ScreenRecorder INSTANCE;
    public static final int NOTIFY_ID = 123456;
    private MediaProjectionManager mediaProjectionManager =null;

    private NotificationManager notificationManager;
    private GenericStream genericStream;
    private MediaProjection mediaProjection;
    private boolean mIsMuted = false;
    private boolean mIsStreaming = false;
    private boolean isStreaming = true;
    private int mResultCode;
    private String recordPath;
    private Intent mResultData;
    private String url;
    private int mScreenWidth = 1280;
    private int mScreenHeight= 960;
    private int mScreenDensity;
    private final IBinder binder = new LocalBinder();
    //    public NotificationManager notificationManager;
    private static final String CHANNEL_ID = "media_projection_channel";
    public int fps = 60;
    // 屏幕较低
    public int rotation = 0;
    private int sampleRate = 32000;
    private boolean isStereo = true;
    private int aBitrate = 128 * 1000;
    private ConnectChecker callback;
    private int selectedAudioSource = 1000058;
    // 延迟推流
 public  int iFrameInterval = 3;
  // 轮廓
    public  int profile = 2;
    private int vBitrate = 1200 * 1000;
    public ScreenRecorder() {
    }

    private static final int NOTIFICATION_ID = 1;


    public void onCreate() {
        Log.i("onCreate", "onCreate");
      try {
          super.onCreate();
          mediaProjectionManager =  (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);

          notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
              NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, NotificationManager.IMPORTANCE_HIGH);
              notificationManager.createNotificationChannel(channel);
          }
          genericStream = new GenericStream(getApplicationContext(),  this, new NoVideoSource(), new MicrophoneSource());
          genericStream.getGlInterface().setForceRender(true, fps);
          boolean prepared = false;
          try {
              int w  = this.mScreenWidth ;
              int h = this.mScreenHeight;
              prepared = genericStream.prepareVideo(w, h, vBitrate, fps,iFrameInterval,rotation,profile,2) &&
                      genericStream.prepareAudio(sampleRate, isStereo, aBitrate, true, true);
          } catch (IllegalArgumentException e) {
              throw new RuntimeException(e.toString());
          }
          if (prepared) INSTANCE = this;
          else new ToastUtils(this, "Invalid audio or video parameters, prepare failed", 3);
          Log.i("onCreate", "onCreate-end");
      } catch (RuntimeException e ){
          Log.e("ScreenRecorder-onCreate", "onCreate失败: " + e.toString());
      }
        // 创建前台服务通知

    }

    private void keepAliveTrick() {
        try {
            Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                    .setSmallIcon(android.R.drawable.ic_menu_camera)
                    .setSilent(true)
                    .setOngoing(false)
                    .build();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION);
            } else {
                startForeground(NOTIFICATION_ID, notification);
            }
        }catch (RuntimeException e) {
            Log.e("keepAliveTrick", "keepAliveTrick失败: " + e.toString());
        }
    }

    public IBinder onBind(Intent intent) {
        return binder;
    }

    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "RTP Display service destroy");
        stopStream();
        INSTANCE = null;
        //release stream and media projection properly
        genericStream.release();
        if (mediaProjection != null) {
            mediaProjection.stop();
        }
        mediaProjection = null;
    }

    // 请求权限的回掉
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("onStartCommand", "onStartCommand");
        try {
            this.mResultCode = intent.getIntExtra("resultCode", 1);
            this.mResultData = intent.getParcelableExtra("data");
            this.url = intent.getStringExtra("url");

            if (this.prepareStream(this.mResultCode, this.mResultData)) {
                INSTANCE = this;
            }


            return START_STICKY;
        } catch (RuntimeException e) {

            Log.e("ScreenRecorder", "初始化失败: " + e.toString());
            return START_STICKY;
        }

    }

    private void getScreenBaseInfo() {
//        this.mScreenWidth = ScreenUtils.getScreenWidth(this);
//        this.mScreenHeight = ScreenUtils.getScreenHeight(this);
        this.mScreenDensity = ScreenUtils.getScreenDensityDpi(this);
    }

    public Intent sendIntent() {
        return mediaProjectionManager.createScreenCaptureIntent();
    }

    public boolean isStreaming() {
        return genericStream.isStreaming();
    }

    public boolean isRecording() {
        return genericStream.isRecording();
    }

    public void stopStream() {
        if (genericStream.isStreaming()) {
            genericStream.stopStream();
            notificationManager.cancel(NOTIFY_ID);
        }
    }

    public void setCallback(ConnectChecker connectChecker) {
        this.callback = connectChecker;
    }


    public boolean prepareStream(int resultCode, Intent data) {
        Log.i("prepareStream", "prepareStream");
        keepAliveTrick();
        stopStream();
        if (mediaProjection != null) {
            mediaProjection.stop();
        }
        mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
        ScreenSource screenSource = new ScreenSource(getApplicationContext(), mediaProjection);
        try {
            genericStream.getGlInterface().setCameraOrientation(0);
            genericStream.changeVideoSource(screenSource);
            toggleAudioSource(selectedAudioSource);
            Log.i("prepareStream", "prepareStream-end");
            return true;
        } catch (IllegalArgumentException e) {
            Log.e("prepareStream", "prepareStream失败: " + e.toString());
            return false;
        }
    }

//    public void getCurrentAudioSource() {
//        AudioSource AudioSource = genericStream.getAudioSource();
//    }

    public void toggleAudioSource(int itemId) {
        switch (itemId) {
            case 1000058:
                selectedAudioSource = 1000058;
                if (genericStream.getAudioSource() instanceof MicrophoneSource) return;
                genericStream.changeAudioSource(new MicrophoneSource());
                break;
//            case 1000061:
//                selectedAudioSource = 1000061;
//                if (genericStream.getAudioSource() instanceof InternalAudioSource) return;
//                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//                    genericStream.changeAudioSource(new InternalAudioSource(mediaProjection, null));
//                }
//                break;
//            case 1000056:
//                selectedAudioSource = 1000056;
//                if (genericStream.getAudioSource() instanceof MixAudioSource) return;
//                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//                    MixAudioSource mixSource = new MixAudioSource(mediaProjection, MediaRecorder.AudioSource.DEFAULT);
//                    mixSource.setMicrophoneVolume(2f);
//                    genericStream.changeAudioSource(mixSource);
//                }
//                break;
        }
    }

    public void toggleRecord(Consumer<RecordController.Status> state) {
        if (!genericStream.isRecording()) {
            // Start recording
            File folderPath = PathUtils.getRecordPath();
            if (!folderPath.exists()) folderPath.mkdirs();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault());
            recordPath = folderPath.getAbsolutePath() + "/" + sdf.format(new Date()) + ".mp4";
            genericStream.startRecord(recordPath, status -> {
                if (status == RecordController.Status.RECORDING) {
                    state.accept(RecordController.Status.RECORDING);
                }
            });
            state.accept(RecordController.Status.STARTED);
        } else {
            // Stop recording
            genericStream.stopRecord();
            state.accept(RecordController.Status.STOPPED);
            PathUtils.updateGallery(this, recordPath);
        }
    }

    public void startStream(String endpoint) {
        if (!genericStream.isStreaming()) genericStream.startStream(endpoint);
    }

    // 切换静音
    public void toggleMicrophoneMute(boolean isMuted) {
        mIsMuted = isMuted;
    }


    public boolean ismIsStreaming() {
        return mIsStreaming;
    }

    public void onConnectionStarted(String url) {
        if (callback !=null){
            callback.onConnectionStarted(url);
        }

    }

    public void onConnectionSuccess() {
        if (callback !=null){
            callback.onConnectionSuccess();
        }

    }

    public void onNewBitrate(long bitrate) {
        if (callback !=null){
        callback.onNewBitrate(bitrate);
        }
    }

    public void onConnectionFailed(String reason) {
            if (callback !=null){
                callback.onConnectionFailed(reason);
        }

    }

    public void onDisconnect() {
            if (callback !=null){
                callback.onDisconnect();
            }

    }

    public void onAuthError() {
        if (callback !=null){
            callback.onAuthError();
        }

    }

    public void onAuthSuccess() {
        if (callback !=null){callback.onAuthSuccess();}

    }


    // Binder类，用于提供对外的接口
    public class LocalBinder extends Binder {
        public ScreenRecorder getService() {
            return ScreenRecorder.this;
        }
    }
}